<template>
    <view style="height: 100%">
        <movable-area :style="{ width: '100%', height: allHeight + 'px' }">
            <movable-view
                v-for="(item, index) in controlsArray"
                :key="item.mode"
                :x="0"
                :y="item.y"
                :style="{ height: itemHeight + 'px', width: '100%' }"
                direction="all"
                class="movable-view"
                @touchstart="onHandleDragStart(index)"
                @change="onHandleMoving(index, $event)"
                @touchend="onHandleDragEnd"
            >
                <!-- 这里可以放置步骤的详细内容 -->
                <view style="background-color: aqua; padding: 20rpx 0">{{ index }}</view>
            </movable-view>
        </movable-area>
    </view>
</template>

<script setup lang="ts">
const controlsArray = ref([]);
const cloneList = ref([]);
const activeIndex = ref(-1);
const oldIndex = ref(-1);
const moveToIndex = ref(-1);
const allHeight = ref(300);
const itemHeight = ref(50);

const deepCopy = (source) => {
    return JSON.parse(JSON.stringify(source));
};

const initList = (e = []) => {
    const newList = deepCopy(e);
    controlsArray.value = newList.map((item, index) => {
        return {
            ...item,
            y: index * itemHeight.value,
            key: Math.random() + index
        };
    });
    //拷贝一份初始list值
    cloneList.value = deepCopy(controlsArray.value);
};

// 拖拽开始
const onHandleDragStart = (index) => {
    activeIndex.value = index;
    oldIndex.value = index;
};
const onHandleMoving = (index, e) => {
    if (e.detail.source !== "touch") return;
    const { x, y } = e.detail;
    const currentY = Math.floor((y + itemHeight.value / 2) / itemHeight.value);

    moveToIndex.value = Math.min(currentY, controlsArray.value.length - 1);

    //更新移动后的位置
    if (oldIndex.value !== moveToIndex.value && oldIndex.value !== -1 && moveToIndex.value !== -1) {
        const newList = deepCopy(cloneList.value);
        //交换位置
        newList.splice(moveToIndex.value, 0, ...newList.splice(activeIndex.value, 1));

        controlsArray.value.forEach((item, index) => {
            if (index !== activeIndex.value) {
                const itemIndex = newList.findIndex((val) => val.id === item.id);
                item.y = itemIndex * itemHeight.value;
            }
        });
        oldIndex.value = moveToIndex.value;
    }
};
const onHandleDragEnd = (e) => {
    if (moveToIndex.value !== -1 && activeIndex.value !== -1 && moveToIndex.value !== activeIndex.value) {
        cloneList.value.splice(moveToIndex.value, 0, ...cloneList.value.splice(activeIndex.value, 1));
    }

    // 重新排序下更新后的位置。
    initList(cloneList.value);

    activeIndex.value = -1;
    oldIndex.value = -1;
    moveToIndex.value = -1;
};

onBeforeMount(() => {
    for (let i = 0; i < 12; i++) {
        let info = {
            id: i,
            desc: "测试" + i
        };
        controlsArray.value.push(info);
    }
    allHeight.value = 12 * itemHeight.value;
    initList(controlsArray.value);
});
</script>

<style>
.movable-area {
}

.movable-view {
}
</style>
